package com.clp.protocol.iec104.server;

import javax.annotation.Nullable;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

public class TaTokenPool implements CtrlTokenPool<TaToken> {
    private final Map<Integer, TaToken> tokenMap = new HashMap<>(32);
    private final Function<Integer, TaToken> tokenCreator;

    public TaTokenPool(Function<Integer, TaToken> tokenCreator) {
        this.tokenCreator = tokenCreator;
    }

    /**
     * 申请 token
     * @param address 要申请的信息体地址
     * @return
     */
    @Nullable
    @Override
    public synchronized TaToken applyFor(int address, SlaveChannel slaveChannel) {
        TaToken token = tokenMap.computeIfAbsent(address, tokenCreator);
        if (token.getApplier() != null) return null; // 当前已经有了申请者了，申请失败
        token.setApplier(slaveChannel);
        return token;
    }

    @Override
    public synchronized boolean returnBack(TaToken token) {
        return returnBack0(token);
    }

    /**
     * 如果是当前token池的token，归还成功；否则，归还失败
     * @param token
     * @return
     */
    private boolean returnBack0(TaToken token) {
        TaToken theToken = tokenMap.get(token.getAddress());
        if (token != theToken) {
            return false; // 相同地址，但是不是同一个token对象，说明是非池中申请的，拒绝归还
        }

        theToken.removeApplier();
        return true;
    }

    /**
     * 归还token
     * @param tokens
     * @return 如果没有全部归还，返回false
     */
    @Override
    public synchronized boolean returnBack(Collection<TaToken> tokens) {
        boolean allReturned = true;
        for (TaToken token : tokens) {
            if (!returnBack0(token)) {
                allReturned = false;
            }
        }
        return allReturned;
    }
}
